﻿using System;
using NServiceBus.Management.Managers.Impl;
using NServiceBus.Management.Messages.EndpointControl;
using NServiceBus.Management.Messages.Statistics;
using NServiceBus.Management.Messages.Status;
using NServiceBus.Unicast.Transport;
using NUnit.Framework;
using Rhino.Mocks;
using Rhino.Mocks.Interfaces;

namespace NServiceBus.Management.UnitTests.Managers
{

    [TestFixture]
    public class The_statistics_manager_should
    {
        [Test]
        public void Send_endpoint_statistics_to_management_service()
        {
            var bus = MockRepository.GenerateMock<IBus>();
            var manager = new StatisticsManager { Bus = bus };
            var startTime = DateTime.Now;

            manager.UpdateStatisticsFor(new OnlineMessage());
            manager.UpdateStatisticsFor(new OfflineMessage());

            manager.SendEndpointStatistics();
            bus.AssertWasCalled(x => x.Send(
                     Arg<IMessage[]>.Matches(
                             p => ((StatisticsMessage)p[0]).Start < DateTime.Now)));

            bus.AssertWasCalled(x => x.Send(
                Arg<IMessage[]>.Matches(
                     p => ((StatisticsMessage)p[0]).End > startTime)));

            bus.AssertWasCalled(x => x.Send(
                                Arg<IMessage[]>.Matches(
                                    p => ((StatisticsMessage)p[0]).NumberOfMessagesReceived.Count == 2)));

           
            //statistics should be cleared after each send, the management endpoint computes totals
            Assert.AreEqual(manager.NumberOfMessagesReceived.Count ,0);

        }

        [Test]
        public void Update_number_of_messages_statistics_when_transport_message_is_received()
        {
            var mock = new MockRepository();
            var transport = mock.StrictMock<ITransport>();

            transport.TransportMessageReceived += null;
            LastCall.IgnoreArguments();

            IEventRaiser raiseEvent = LastCall.GetEventRaiser();

            mock.ReplayAll();

            var manager = new StatisticsManager { Transport = transport };
            var tr = new TransportMessage();

            tr.Body = new IMessage[] { new OfflineMessage(), new OnlineMessage() ,
                new OfflineMessage(),new PingCommand(),new OfflineMessage(),new OnlineMessage()};

            raiseEvent.Raise(this, new TransportMessageReceivedEventArgs(tr));

            Assert.AreEqual(3, manager
                .NumberOfMessagesReceived
                .Count);

            Assert.AreEqual(3, manager
                .NumberOfMessagesReceived[typeof(OfflineMessage)]);
                
            Assert.AreEqual(2, manager
                .NumberOfMessagesReceived[typeof(OnlineMessage)]);
                
            Assert.AreEqual(1, manager
                .NumberOfMessagesReceived[typeof(PingCommand)]);
                


            raiseEvent.Raise(this, new TransportMessageReceivedEventArgs(tr));

            Assert.AreEqual(3, manager
                .NumberOfMessagesReceived.Count);

            Assert.AreEqual(6, manager
                 .NumberOfMessagesReceived[typeof(OfflineMessage)]);
        
            Assert.AreEqual(4, manager
                 .NumberOfMessagesReceived[typeof(OnlineMessage)]);
        
            Assert.AreEqual(2, manager
                 .NumberOfMessagesReceived[typeof(PingCommand )]);
        }

    }
}
